#ifndef ANDROID_PARCEL_H
#define ANDROID_PARCEL_H

#include "Parcelable.h"

namespace android {

class Parcel {
public:
    Parcel();
    ~Parcel();

    Parcel(const Parcel& o) = delete;
    Parcel& operator=(const Parcel& o) = delete;

public:
    const uint8_t* data() const;
    size_t dataSize() const;
    size_t dataAvail() const;
    size_t dataPosition() const;
    size_t dataCapacity() const;

    status_t setDataSize(size_t size);
    void setDataPosition(size_t pos) const;
    status_t setDataCapacity(size_t size);

    void freeData();

public:
    status_t write(const void* data, size_t len);
    void* writeInplace(size_t len);

    status_t writeInt8(const int8_t val);
    status_t writeInt16(const int16_t val);
    status_t writeInt32(const int32_t val);
    status_t writeInt64(const int64_t val);
    status_t writeFloat(const float val);
    status_t writeDouble(const double val);
    status_t writeString(const std::string& str);

    status_t writeInt8Vector(const std::vector<int8_t>& val);
    status_t writeInt16Vector(const std::vector<int16_t>& val);
    status_t writeInt32Vector(const std::vector<int32_t>& val);
    status_t writeInt64Vector(const std::vector<int64_t>& val);
    status_t writeFloatVector(const std::vector<float>& val);
    status_t writeDoubleVector(const std::vector<double>& val);
    status_t writeStringVector(const std::vector<std::string>& val);

public:
    status_t read(void* outData, size_t len) const;
    const void* readInplace(size_t len) const;

    status_t readInt8(int8_t* pArg) const;
    status_t readInt16(int16_t* pArg) const;
    status_t readInt32(int32_t* pArg) const;
    status_t readInt64(int64_t* pArg) const;
    status_t readFloat(float* pArg) const;
    status_t readDouble(double* pArg) const;
    status_t readString(std::string* pArg) const;

    status_t readInt8Vector(std::vector<int8_t>* val) const;
    status_t readInt16Vector(std::vector<int16_t>* val) const;
    status_t readInt32Vector(std::vector<int32_t>* val) const;
    status_t readInt64Vector(std::vector<int64_t>* val) const;
    status_t readFloatVector(std::vector<float>* val) const;
    status_t readDoubleVector(std::vector<double>* val) const;
    status_t readStringVector(std::vector<std::string>* val) const;

    int32_t readInt32() const;

private:
    void initState();
    void freeDataNoInit();

    status_t finishWrite(size_t len);
    status_t growData(size_t len);
    status_t continueWrite(size_t desired);

    template <class T>
    status_t writeAligned(T val);

    template <class T>
    status_t readAligned(T* pArg) const;

    template <class T>
    T readAligned() const;

private:
    status_t mError;
    uint8_t* mData;
    size_t mDataSize;
    size_t mDataCapacity;
    mutable size_t mDataPos;

}; // class Parcel

} // namespace android

#endif // ANDROID_PARCEL_H
